#include "../StdInc.h"

namespace GSTrader
{
	namespace Indicator
	{
		RSI::RSI()
		{
			m_strIndicatorName = "RSI";

			m_n1 = 0;
			m_n2 = 0;
			m_n3 = 0;

			m_pRefSeries = new CDataSeries;
			m_pMaxSeries = new CDataSeries;
			m_pAbsSeries = new CDataSeries;

			m_pMaxSma1 = new SMA;
			m_pMaxSma2 = new SMA;
			m_pMaxSma3 = new SMA;
			m_pAbsSma1 = new SMA;
			m_pAbsSma2 = new SMA;
			m_pAbsSma3 = new SMA;

			m_pRsi1 = m_pResult;
			m_pRsi1->m_strName = "RSI1";

			m_pRsi2 = new CIndicatorResult;
			m_pRsi2->m_strName = "RSI2";
			m_vResult.push_back(m_pRsi2);

			m_pRsi3 = new CIndicatorResult;
			m_pRsi3->m_strName = "RSI3";
			m_vResult.push_back(m_pRsi3);
		}


		RSI::~RSI()
		{
			_delete(m_pRefSeries)
			_delete(m_pMaxSeries)
			_delete(m_pAbsSeries)
			_delete(m_pMaxSma1)
			_delete(m_pMaxSma2)
			_delete(m_pMaxSma3)

			_delete(m_pAbsSma1)
			_delete(m_pAbsSma2)
			_delete(m_pAbsSma3)
		}

		CIndicator* RSI::CreateInstance()
		{
			return new RSI;
		}

		void RSI::SetParam(double* pdParam)
		{
			if (pdParam == NULL)
				return;

			m_n1 = (int)pdParam[0];
			m_n2 = (int)pdParam[1];
			m_n3 = (int)pdParam[2];

			m_pMaxSma1->SetParam(m_n1, 1, bdtClose);
			m_pMaxSma2->SetParam(m_n2, 1, bdtClose);
			m_pMaxSma3->SetParam(m_n3, 1, bdtClose);

			m_pAbsSma1->SetParam(m_n1, 1, bdtClose);
			m_pAbsSma2->SetParam(m_n2, 1, bdtClose);
			m_pAbsSma3->SetParam(m_n3, 1, bdtClose);

			RefreshData();
		}

		void RSI::SetInputSeries(CSeries* pSeries)
		{
			m_pRefSeries->m_nStartIndex = 1; // 
			m_pMaxSeries->m_nStartIndex = 1;
			m_pAbsSeries->m_nStartIndex = 1;

			m_pMaxSma1->SetInputSeries(m_pMaxSeries);
			m_pMaxSma2->SetInputSeries(m_pMaxSeries);
			m_pMaxSma3->SetInputSeries(m_pMaxSeries);

			m_pAbsSma1->SetInputSeries(m_pAbsSeries);
			m_pAbsSma2->SetInputSeries(m_pAbsSeries);
			m_pAbsSma3->SetInputSeries(m_pAbsSeries);

			CIndicator::SetInputSeries(pSeries);
		}

		double RSI::Calculate(int nIndex)
		{
			if (m_pInput == NULL || m_pInput->m_nStartIndex < 0 || m_n1 < 0 || m_n2 < 0 || m_n3 < 0)
				return 0;

			double dPreClose = 0;
			double dClose = m_pInput->GetValue(nIndex, bdtClose);
			if (nIndex > 0)
			{
				dPreClose = m_pInput->GetValue(nIndex - 1, bdtClose);
			}
			m_pRefSeries->SetValue(nIndex, dPreClose);

			double dMax = max(dClose - dPreClose, (double)0);
			double dAbs = abs(dClose - dPreClose);

			m_pMaxSeries->SetValue(nIndex, dMax);
			m_pAbsSeries->SetValue(nIndex, dAbs);

			double dMaxSma1 = m_pMaxSma1->Calculate(nIndex);
			double dMaxSma2 = m_pMaxSma2->Calculate(nIndex);
			double dMaxSma3 = m_pMaxSma3->Calculate(nIndex);
			double dAbsSma1 = m_pAbsSma1->Calculate(nIndex);
			double dAbsSma2 = m_pAbsSma2->Calculate(nIndex);
			double dAbsSma3 = m_pAbsSma3->Calculate(nIndex);

			double dRsi1 = fabs(dAbsSma1) < DBL_MIN ? 0 : (dMaxSma1 / dAbsSma1 * 100);
			double dRsi2 = fabs(dAbsSma2) < DBL_MIN ? 0 : (dMaxSma2 / dAbsSma2 * 100);
			double dRsi3 = fabs(dAbsSma3) < DBL_MIN ? 0 : (dMaxSma3 / dAbsSma3 * 100);

			m_pRsi1->SetValue(nIndex, dRsi1);
			m_pRsi2->SetValue(nIndex, dRsi2);
			m_pRsi3->SetValue(nIndex, dRsi3);
			return 1;
		}

		void RSI::RefreshData()
		{
			if (m_pInput == NULL || m_pInput->m_nStartIndex < 0)
			{
				m_pRsi1->m_pDataSeries->m_nStartIndex = -1;
				m_pRsi2->m_pDataSeries->m_nStartIndex = -1;
				m_pRsi3->m_pDataSeries->m_nStartIndex = -1;
				return;
			}

			int nCount = m_pInput->GetCount();
			int nStartIndex = m_pInput->m_nStartIndex + 2; 

			m_pRsi1->m_pDataSeries->SetSize(nCount, nStartIndex);
			m_pRsi2->m_pDataSeries->SetSize(nCount, nStartIndex);
			m_pRsi3->m_pDataSeries->SetSize(nCount, nStartIndex);

			m_bCalc = true;
		}
	}
}
